#ifndef STX_CORE_DATE_TIME_HPP
#define STX_CORE_DATE_TIME_HPP

#include <ctime>
#include <cstddef>
#include <limits>

#include <string>
#include <iomanip>
#include <iosfwd>

/*
    SI multiples for second:
        1e-24  ys  zeptosecond
        1e-21  zs  zeptosecond
        1e-18  as  attosecond
        1e-15  fs  femtosecond
        1e-12  ps  picosecond
        1e-9   ns  nanosecond
        1e-6   us  microsecond
        1e-3   ms  millisecond
        1e-2   cs  centisecond
        1e-1   ds  decisecond
        1e0     s  second
        1e1   das  decasecond
        1e2    hs  hectosecond
        1e3    ks  kilosecond
        1e6    Ms  megasecond
        1e9    Gs  gigasecond
        1e12   ts  terasecond
        1e15   Ps  petasecond
        1e18   Es  exasecond
        1e21   Zs  zettasecond
        1e24   Ys  yottasecond
*/    

namespace stx {

/*

inline long clocks_to_nanoseconds(std::clock_t clocks)
{
    long ns, adj, billion = 1000000000;
    if (CLOCKS_PER_SEC <= billion) {
        adj = billion/CLOCKS_PER_SEC;
        ns = clocks * adj;
    } else if (CLOCKS_PER_SEC == billion) {
        ns = clocks;
    } else {
        adj = CLOCKS_PER_SEC/billion;
        ns = clocks / adj;
    }
    return ns;
}

//  Datetime routines with subsecond precision - based only on C++ standard library.
//  Note: subsecond precision is implemented via time() and clock() functions.
class date_time
{
public:
    
    date_time()
    {
        adjust_clock();
    }
    
    std::time_t time() const
    {
        return time_;
    }
    
    long nanoseconds() const
    {
        return nanoseconds_;
    }
    
    void update()
    {
        std::clock_t c = std::clock();
        std::time_t t = std::time(NULL);
        nanoseconds_ = clocks_to_nanoseconds(c - clock_ - CLOCKS_PER_SEC*(t - time_));
        if (nanoseconds_ < 0) {
            clock_ += CLOCKS_PER_SEC*(t - time_) + clock_ - c;
            nanoseconds_ = 0;
        }
    }
    
private:
    
    void adjust_clock()
    {
        std::time_t t1, t2;
        std::clock_t c1, c2;
        c1 = std::clock();
        t1 = std::time(NULL);
        while (1) {
            c2 = std::clock();
            t2 = std::time(NULL);
            if (t2 == -1) {
                break;
            }
            if (t2 > t1) {
                time_ = t2;
                clock_ = c2;
                break;
            }
        }
        nanoseconds_ = 0;
    }
    
    long nanoseconds_;
    std::time_t time_;
    std::clock_t clock_;
};

//*/

} // namespace stx

#endif // STX_CORE_DATE_TIME_HPP
